﻿using System.Linq;
using EPiServer.Core;
using PageTypeBuilder;
using TemplateFoundation.CustomProperties;
using TemplateFoundation.PageTypeIcons;
using TemplateFoundation.Tabs;
using TemplateFoundation.Tags;

namespace TemplateFoundation.PageTypes
{
    /// <summary>
    /// Base class for RSS pages
    /// </summary>
    [PageTypeIcon("~/TemplateFoundation/Images/PageIcons/rss.png")]
    public abstract class RssPageBase : PageTypeBase
    {
        private PageDataCollection _pages;

        /// <summary>
        /// Gets or sets the tags used to filter this feed
        /// </summary>
        [PageTypeProperty(
            EditCaption = "Tags filter",
            HelpText = "Use this property to limit the feed to pages matching the specified tags",
            UniqueValuePerLanguage = true,
            SortOrder = 100,
            Type = typeof (PropertyTags),
            Tab = typeof (RelatedTab))]
        public override TagCollection Tags { get; set; }

        /// <summary>
        /// Gets or sets the contact used to filter this feed
        /// </summary>
        [PageTypeProperty(
            EditCaption = "Contact filter",
            HelpText = "Use this property to limit the feed to articles by a specific contact",
            UniqueValuePerLanguage = true,
            SortOrder = 110,
            Type = typeof(PropertyContact),
            Tab = typeof(RelatedTab))]
        public override PageReference PageContact { get; set; }

        /// <summary>
        /// Gets or sets an alternate URL to use for this feed
        /// </summary>
        [PageTypeProperty(
            EditCaption = "Alternate URL",
            HelpText = "Alternate URL for this feed, for example a Feedburner URL",
            SortOrder = 100,
            Type = typeof (PropertyString),
            Tab = typeof (SeoTab))]
        public virtual string AlternateUrl { get; set; }

        /// <summary>
        /// Gets or sets whether to skip auto-discovery link for a feed
        /// </summary>
        [PageTypeProperty(
            EditCaption = "Suppress auto-discovery",
            HelpText = "If checked this feed will not be included among auto-discovery links",
            Type = typeof(PropertyBoolean),
            Tab = typeof(SettingsTab))]
        public virtual bool DisableAutoDiscovery { get; set; }

        /// <summary>
        /// Gets or sets whether full content of pages should be included in the feed
        /// </summary>
        [PageTypeProperty(
            EditCaption = "Include full content",
            HelpText = "If checked the entire content of pages will be included as opposed to just the description",
            Type = typeof(PropertyBoolean),
            Tab = typeof(SeoTab))]
        public virtual bool IncludeFullContent { get; set; }

        /// <summary>
        /// Gets or sets a number to limit the number of items included in the feed
        /// </summary>
        [PageTypeProperty(
            EditCaption = "Max item count",
            HelpText = "If set to a positive number this limits the maximum number of items to include in the feed",
            Type = typeof(PropertyNumber),
            Tab = typeof(SettingsTab))]
        public virtual int? MaxFeedItemCount { get; set; }

        /// <summary>
        /// Gets or sets the name of the page type property to use for the feed items' date
        /// </summary>
        [PageTypeProperty(
            EditCaption = "Item data property",
            HelpText = "The name of the page type property to use for the feed items' date",
            Type = typeof(PropertyString),
            Tab = typeof(SettingsTab))]
        public virtual string FeedItemDatePropertyName { get; set; }

        /// <summary>
        /// Gets the pages to include in the RSS feed
        /// </summary>
        /// <remarks>Defaults to the pages returned by the GetPages() method</remarks>
        public virtual PageDataCollection Pages
        {
            get
            {
                if (_pages == null)
                {
                    _pages = GetPages();
                }

                if (MaxFeedItemCount.HasValue && MaxFeedItemCount.Value>0 && MaxFeedItemCount.Value < _pages.Count)
                {
                    _pages = new PageDataCollection(_pages.Take(MaxFeedItemCount.Value));
                }

                return _pages;
            }
            protected set
            {
                if (_pages==null)
                {
                    _pages = new PageDataCollection();
                }

                if (Tags==null || Tags.Count==0)
                {
                    _pages = value;
                }
                else // Filter by Tags property
                {
                    foreach (var page in
                        from page in value.OfType<PageTypeBase>()
                        from tag in Tags
                        where page.Tags.Contains(tag)
                        select page)
                        {
                            _pages.Add(page);
                        }
                }
            }
        }

        /// <summary>
        /// Returns the pages to include in the RSS feed
        /// </summary>
        /// <returns></returns>
        public abstract PageDataCollection GetPages();
    }
}